
'''
    Software License

    Copyright (C) 2021-05-24  Xoronos

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
'''

'''
    Liabilities

    The software is provided "AS IS" without any warranty of any kind, either expressed,
    implied, or statutory, including, but not limited to, any warranty that the software
    will conform to specifications, any implied warranties of merchantability, fitness
    for a particular purpose, and freedom from infringement, and any warranty that the
    documentation will conform to the software, or any warranty that the software will
    be error free.

    In no event shall Xoronos be liable for any damages, including, but not limited to,
    direct, indirect, special or consequential damages, arising out of, resulting from,
    or in any way connected with this software, whether or not based upon warranty,
    contract, tort, or otherwise, whether or not injury was sustained by persons or
    property or otherwise, and whether or not loss was sustained from, or arose out of
    the results of, or use of, the software or services provided hereunder.
    
    To request the provided software under a different license you can contact us at
    support@xoronos.com
'''

import xrnlib256 as xrn

#####################################################
##                   Introduction                  ##
#####################################################
## This code example shows how to compute the      ##
## polyvalent key exchange.                        ##
#####################################################

#####################################################
##                   Pre-requisits                 ##
#####################################################
## The Xoron matrix decompressed data structure    ##
## needs to be mined before running this code      ##
## example. Some examples on how to mine Xoron     ##
## matrices can be found in                        ##
## generate_xrn_matrix_all_rnd.py or               ##
## generate_xrn_matrix_one_third.py                ##
##                                                 ##
## Two monovalent, and polyvalent keys.            ##
## Two polyvalent proofs.                          ##
##                                                 ##
## An example on how to generate keys and proofs   ##
## can be found in                                 ##
## generate_keys_with_wrapper_functions.c          ##
#####################################################

def generate_monovalent_keys_alice_bob ():

    # library run time settings

    settings = xrn.xrn_crypto_extra_settings_t ()

    # all the subfields of settings, can be found in xrn_crypto_extra_settings_t.txt

    #############################
    ## Variable initialization ##
    #############################

    # Initialize default run time settings
    # In this code example only the settings.rnd_str is used
    # In the xrn_load_default_settings function xrn_make_monovalent_key_wrapper string is used.
    # Other functions names can be also used to initialize settings

    if ( xrn.XSUCCESS != xrn.xrn_load_default_settings( settings ) ) :
        return -1

    ##########################
    ## Alice Monovalent key ##
    ##########################

    print( "making Alice monovalent key ..." )

    start_timestamp = 0
    end_timestamp = 0xffffffffffffffff

    alice_monovalent_key_fp = xrn.fopen( "alice_monovalent_key.xf", "wb" )
    alice_polyvalent_key_fp = xrn.fopen( "alice_polyvalent_key.xf", "wb" )
    alice_polyvalent_proof_fp = xrn.fopen( "alice_polyvalent_proof.xf", "wb" )
    decompressed_xrn_matrix_fp = xrn.fopen( "xrn_matrix.xm", "rb" )

    if ( ( alice_monovalent_key_fp == None ) or ( alice_polyvalent_key_fp == None )
         or ( alice_polyvalent_proof_fp == None ) or ( decompressed_xrn_matrix_fp == None ) ) :
        return -1

    if ( xrn.XSUCCESS != xrn.xrn_make_monovalent_key_wrapper( decompressed_xrn_matrix_fp,        # the Xoron matrix file pointer
                                                   start_timestamp,     # start of validity in unix time
                                                   end_timestamp,       # end of validity in unix time 
                                                   alice_polyvalent_key_fp,     # the polyvalent key (secret key)
                                                   alice_polyvalent_proof_fp,   # the polyvalent proof (secret proof of having generated the monovalent key)
                                                   alice_monovalent_key_fp,     # the monovalent key (key that can be disclosed)
                                                   settings ) ) :
        xrn.fclose( decompressed_xrn_matrix_fp )
        xrn.fclose( alice_monovalent_key_fp )
        xrn.fclose( alice_polyvalent_key_fp )
        xrn.fclose( alice_polyvalent_proof_fp )
        return -1

    if ( ( 0 != xrn.fclose( alice_monovalent_key_fp ) ) or ( 0 != xrn.fclose( alice_polyvalent_key_fp ) )
         or ( 0 != xrn.fclose( alice_polyvalent_proof_fp ) )
         or ( 0 != xrn.fclose( decompressed_xrn_matrix_fp ) ) ) :
        return -1

    ########################
    ## Bob Monovalent key ##
    ########################

    print( "making Bob monovalent key ..." )

    start_timestamp = 0
    end_timestamp = 0xffffffffffffffff

    bob_monovalent_key_fp = xrn.fopen( "bob_monovalent_key.xf", "wb" )
    bob_polyvalent_key_fp = xrn.fopen( "bob_polyvalent_key.xf", "wb" )
    bob_polyvalent_proof_fp = xrn.fopen( "bob_polyvalent_proof.xf", "wb" )
    decompressed_xrn_matrix_fp = xrn.fopen( "xrn_matrix.xm", "rb" )

    if ( ( bob_monovalent_key_fp == None ) or ( bob_polyvalent_key_fp == None )
         or ( bob_polyvalent_proof_fp == None ) or ( decompressed_xrn_matrix_fp == None ) ) :
        return -1

    if ( xrn.XSUCCESS != xrn.xrn_make_monovalent_key_wrapper( decompressed_xrn_matrix_fp,        # the Xoron matrix file pointer
                                                   start_timestamp,     # start of validity in unix time
                                                   end_timestamp,       # end of validity in unix time 
                                                   bob_polyvalent_key_fp,       # the polyvalent key (secret key)
                                                   bob_polyvalent_proof_fp,     # the polyvalent proof (secret proof of having generated the monovalent key)
                                                   bob_monovalent_key_fp,       # the monovalent key (key that can be disclosed)
                                                   settings ) ) :
        xrn.fclose( decompressed_xrn_matrix_fp )
        xrn.fclose( bob_monovalent_key_fp )
        xrn.fclose( bob_polyvalent_key_fp )
        xrn.fclose( bob_polyvalent_proof_fp )
        return -1

    if ( ( 0 != xrn.fclose( bob_monovalent_key_fp ) ) or ( 0 != xrn.fclose( bob_polyvalent_key_fp ) )
         or ( 0 != xrn.fclose( bob_polyvalent_proof_fp ) )
         or ( 0 != xrn.fclose( decompressed_xrn_matrix_fp ) ) ) :
        return -1

    # An alternative to the xrn_make_monovalent_key_wrapper is the xrn_make_monovalent_key function         
    # if ( xrn.XSUCCESS !=
    #      xrn.xrn_make_monovalent_key ( xrn_matrix, # the xrn_matrix is of the type ( xrn_matrix_t * ) 
    #                             start_timestamp,     # start of validity in unix time                   
    #                             end_timestamp,       # end of validity in unix time 
    #                             xpolyvalent_key,  # the polyvalent key is of the type ( xpolyvalent_key_t ) 
    #                             xpolyvalent_proof, # the polyvalent proof is of the type ( xpolyvalent_proof_t )
    #                             xmonomial_key  # the xmonomial_key is of the type ( xmonovalent_key_t * )
    #                        ) ) :

    return 0


def xrn_polyvalant_key_exchange_wrapper_example( ):

    ##########################
    ## Variable definitions ##
    ##########################

    # library run time settings

    settings = xrn.xrn_crypto_extra_settings_t ()

    # all the subfields of settings, can be found in xrn_crypto_extra_settings_t.txt

    ##########################
    ## Initialize variables ##
    ##########################

    # Initialize default run time settings

    if ( xrn.XSUCCESS != xrn.xrn_load_default_settings( settings ) ) :
        return -1

    alice_monovalent_key_fp = xrn.fopen( "alice_monovalent_key.xf", "rb" )
    bob_monovalent_key_fp = xrn.fopen( "bob_monovalent_key.xf", "rb" )
    alice_polyvalent_key_fp = xrn.fopen( "alice_polyvalent_key.xf", "rb" )
    alice_polyvalent_proof_fp = xrn.fopen( "alice_polyvalent_proof.xf", "rb" )
    alice_shared_polyvalent_key_fp = xrn.fopen( "alice_shared_polyvalent_key.xf", "wb" )
    decompressed_xrn_matrix_fp = xrn.fopen( "xrn_matrix.xm", "rb" )

    if ( ( alice_shared_polyvalent_key_fp == None ) or ( bob_monovalent_key_fp == None )
         or ( alice_monovalent_key_fp == None ) or ( alice_polyvalent_key_fp == None )
         or ( alice_polyvalent_proof_fp == None ) or ( decompressed_xrn_matrix_fp == None ) ) :
        return -1

    #########################
    ## Generate common key ##
    #########################

    if ( xrn.XSUCCESS != xrn.xrn_exchange_polyvalent_key_wrapper( decompressed_xrn_matrix_fp, # Xoron matrix file pointer
                                                          alice_monovalent_key_fp,      # Xoron internal monovalent key file pointer
                                                          bob_monovalent_key_fp,        # Xoron external monovalent key file pointer
                                                          alice_polyvalent_key_fp,      # Xoron internal polyvalent key file pointer
                                                          alice_polyvalent_proof_fp,    # Xoron internal polyvalent proof file pointer
                                                          alice_shared_polyvalent_key_fp,       # output polyvalent key file pointer
                                                          settings      # the run time settings
          ) ) :

        xrn.fclose( alice_monovalent_key_fp )
        xrn.fclose( bob_monovalent_key_fp )
        xrn.fclose( alice_polyvalent_key_fp )
        xrn.fclose( alice_polyvalent_proof_fp )
        xrn.fclose( alice_shared_polyvalent_key_fp )
        xrn.fclose( decompressed_xrn_matrix_fp )

        return -1


    if ( ( 0 != xrn.fclose( alice_monovalent_key_fp ) ) or ( 0 != xrn.fclose( bob_monovalent_key_fp ) )
         or ( 0 != xrn.fclose( alice_polyvalent_key_fp ) ) or ( 0 != xrn.fclose( alice_polyvalent_proof_fp ) )
         or ( 0 != xrn.fclose( alice_shared_polyvalent_key_fp ) )
         or ( 0 != xrn.fclose( decompressed_xrn_matrix_fp ) ) ) :
        return -1

    # An alternative way to perform the same computation can be achieved using the xrn_exchange_polyvalent_key function
    # if ( xrn.XSUCCESS != xrn.xrn_exchange_polyvalent_key( xrn_matrix,    # xrn_matrix is of the type ( xrn_matrix_t * )
    #                                               alice_monovalent_key, # alice_monovalent_key is of the type ( xmonovalent_key_t * )
    #                                               bob_monovalent_key,     # bob_monovalent_key is of the type ( xmonovalent_key_t * )
    #                                               alice_polyvalent_key,   # alice_polyvalent_key is of the type ( xpolyvalent_key_t * )
    #                                               alice_polyvalent_proof, # alice_polyvalent_proof is of the type ( xpolyvalent_proof_t * )
    #                                               alice_shared_polyvalent_key,   # alice_shared_polyvalent_key is of the type ( xpolyvalent_key_t * )
    #                                               settings 
    #       ) ) :

    return 0

def xrn_check_monovalent_key_wrapper_example( ):

    ##########################
    ## Variable definitions ##
    ##########################

    # library run time settings

    settings = xrn.xrn_crypto_extra_settings_t() 

    # all the subfields of settings, can be found in xrn_crypto_extra_settings_t.txt

    ##########################
    ## Initialize variables ##
    ##########################

    # Initialize default run time settings

    if ( xrn.XSUCCESS != xrn.xrn_load_default_settings( settings ) ) :
        return -1

    ###########################
    ## Verify monovalent key ##
    ###########################

    bob_monovalent_key_fp = xrn.fopen( "bob_monovalent_key.xf", "rb" )
    bob_polyvalent_proof_fp = xrn.fopen( "bob_polyvalent_proof.xf", "rb" )
    decompressed_xrn_matrix_fp = xrn.fopen( "xrn_matrix.xm", "rb" )

    if ( ( bob_monovalent_key_fp == None ) or ( bob_polyvalent_proof_fp == None )
         or ( decompressed_xrn_matrix_fp == None ) ) :
        return -1

    if ( xrn.XSUCCESS != xrn.xrn_check_monovalent_key_wrapper( decompressed_xrn_matrix_fp,
                                                              bob_monovalent_key_fp,
                                                              bob_polyvalent_proof_fp, settings ) ) :
        xrn.fclose( bob_monovalent_key_fp )
        xrn.fclose( bob_polyvalent_proof_fp )
        xrn.fclose( decompressed_xrn_matrix_fp )
        return -1

    if ( ( 0 != xrn.fclose( bob_monovalent_key_fp ) ) or ( 0 != xrn.fclose( bob_polyvalent_proof_fp ) )
         or ( 0 != xrn.fclose( decompressed_xrn_matrix_fp ) ) ) :
        return -1

    # An alternative way to perform the same computation can be achieved using the xrn_exchange_polyvalent_key function
    # if ( xrn.XSUCCESS != xrn.xrn_check_monovalent_key_wrapper( xrn_matrix,    # xrn_matrix is of the type ( xrn_matrix_t * )
    #                                                           bob_monovalent_key, # bob_monovalent_key is of the type ( xmonovalent_key_t * )
    #                                                           bob_polyvalent_proof, # bob_polyvalent_key is of the type ( xpolyvalent_proof_t * )
    #                                                           settings )):

    return 0



#############
## Logging ##
#############

# Set the default logging file streams
# errors -> stderr
# warnings -> stdout
# notifications -> stdout
# debug -> stdout

xrn.xrn_set_default_log(  )

# To change the default logging you can use the functions below,
# where fp is the opened file pointer
# 
# xrn_change_error_log( fp )
# xrn_change_warning_log( fp )
# xrn_change_notification_log( fp )
# xrn_change_debug_log( fp )

if ( 0 != generate_monovalent_keys_alice_bob(  ) ) :
    exit( -1 )

print( "compute common polyvalent key ... " )
if ( 0 != xrn_polyvalant_key_exchange_wrapper_example(  ) ) :
    print( "error in key exchange " )
    exit( -1 )

print( "verify exchanged monovalent key ... " )
if ( 0 != xrn_check_monovalent_key_wrapper_example(  ) ) :
    print( "error in key verification " )
    exit( -1 )


print( "computed and verified common key " )

exit( 0 )


